//
//  AKUIAppDelegate.m
//  AKUI
//
//  Created by Ben Chen on 3/8/08.
//  Copyright Sleeper 2008. All rights reserved.
//

#import "AKUIAppDelegate.h"
#import "AKUIRenderView.h"

#import "AKDrawing.h"
#import "AKTTT.h"
#import "AKPlayer.h"

// Tic Tac Toe
#import "AKTTTAIPlayer.h"
#import "AKTTTBasicInfoProvider.h"
#import "AKTTTImageProvider.h"
#import "AKTTTGeometryProvider.h"
#import "AKTTTStateMaintainer.h"

// Othello
#import "AKOTBasicInfoProvider.h"
#import "AKOTGeometryProvider.h"
#import "AKOTImageProvider.h"
#import "AKOTStateMaintainer.h"

#import "AKBasicAnimationProvider.h"
#import "AKMediator.h"
#import "AKUIHumanPlayer.h"

NSString * const kAKUIAppDelegateArchivedFileName	= @"AKArchived1.aka";
NSString * const kAKUIAppDelegateStateMaintainerKey = @"_StateMaintainerKey";
NSString * const kAKUIAppDelegateGameTypeKey		= @"_GameTypeKey";

NSString * const kAKUIAppDelegateInfoProviderClassNameKey		= @"_InfoProviderKey";
NSString * const kAKUIAppDelegateGeoProviderClassNameKey		= @"_GeoProviderKey";
NSString * const kAKUIAppDelegateImageProviderClassNameKey		= @"_ImageProviderKey";
NSString * const kAKUIAppDelegateStateMaintainerClassNameKey	= @"_StateMaintainerKey";
NSString * const kAKUIAppDelegateAniProviderClassNameKey		= @"_AniProviderKey";
NSString * const kAKUIAppDelegatePlayerNamesArrayKey			= @"_PlayerNamesArrayKey";

@implementation AKUIContainer

@synthesize window, contentView, gameType;

#pragma mark Archiving

- (id)initWithCoder:(NSCoder*)coder {
	[super init];

	stateMaintainer = [coder decodeObjectForKey:kAKUIAppDelegateStateMaintainerKey];
	gameType		= [coder decodeIntegerForKey:kAKUIAppDelegateGameTypeKey];
	
	infoProvider	= [[NSClassFromString([coder decodeObjectForKey:kAKUIAppDelegateInfoProviderClassNameKey]) alloc] init];
	geoProvider		= [[NSClassFromString([coder decodeObjectForKey:kAKUIAppDelegateGeoProviderClassNameKey]) alloc] init];
	
	imageProvider	= [[NSClassFromString([coder decodeObjectForKey:kAKUIAppDelegateImageProviderClassNameKey]) alloc] init];
	stateMaintainer	= [[NSClassFromString([coder decodeObjectForKey:kAKUIAppDelegateStateMaintainerClassNameKey]) alloc] init];
	aniProvider		= [[NSClassFromString([coder decodeObjectForKey:kAKUIAppDelegateAniProviderClassNameKey]) alloc] init];
	
	NSArray *playerNames = [coder decodeObjectForKey:kAKUIAppDelegatePlayerNamesArrayKey];
	NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:[playerNames count]];
	for (NSString *playerClassName in playerNames) {
		id <AKPlayer> thePlayer = [[NSClassFromString(playerClassName) alloc] init];
		[tempArray addObject:thePlayer];
	}
	players = [tempArray copy];
	
	return self;
}

- (void)encodeWithCoder:(NSCoder*)coder {
	[coder encodeObject:stateMaintainer forKey:kAKUIAppDelegateStateMaintainerKey];
	[coder encodeInteger:gameType forKey:kAKUIAppDelegateGameTypeKey];
	
	[coder encodeObject:NSStringFromClass([infoProvider class])		forKey:kAKUIAppDelegateInfoProviderClassNameKey];
	[coder encodeObject:NSStringFromClass([geoProvider class])		forKey:kAKUIAppDelegateGeoProviderClassNameKey];
	[coder encodeObject:NSStringFromClass([imageProvider class])	forKey:kAKUIAppDelegateImageProviderClassNameKey];
	[coder encodeObject:NSStringFromClass([stateMaintainer class])	forKey:kAKUIAppDelegateStateMaintainerClassNameKey];
	[coder encodeObject:NSStringFromClass([aniProvider class])		forKey:kAKUIAppDelegateAniProviderClassNameKey];

	NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:[players count]];
	for (id <AKPlayer> thePlayer in players) {
		[tempArray addObject:NSStringFromClass([thePlayer class])];
	}
	[coder encodeObject:[tempArray copy] forKey:kAKUIAppDelegatePlayerNamesArrayKey];
}

#pragma mark Assembling 

// window
- (void)createWindowAndView {
	// Create window
	self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
	
	// Set up content view
	self.contentView = [[[AKUIRenderView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
	[window addSubview:contentView];
}

// Othello
- (void)assembleOthello {
	AKUIHumanPlayer *player1 = [[AKUIHumanPlayer alloc] initWithSide:0 numOfPlayers:2];
	AKUIHumanPlayer *player2 = [[AKUIHumanPlayer alloc] initWithSide:1 numOfPlayers:2];
	players = [[NSArray alloc] initWithObjects:player1, player2, nil];
	
	infoProvider	= [[AKOTBasicInfoProvider alloc] init];
	geoProvider		= [[AKOTGeometryProvider alloc] init];
	imageProvider	= [[AKOTImageProvider alloc] init];
	stateMaintainer	= [[AKOTStateMaintainer alloc] init];
	
	aniProvider = [[AKBasicAnimationProvider alloc] init];
}

// Tic Tac Toe
- (void)assembleTicTacToe {
	AKUIHumanPlayer *player1 = [[AKUIHumanPlayer alloc] initWithSide:0 numOfPlayers:2];
	AKUIHumanPlayer *player2 = [[AKUIHumanPlayer alloc] initWithSide:1 numOfPlayers:2];
	players = [[NSArray alloc] initWithObjects:player1, player2, nil];
	
	infoProvider = [[AKTTTBasicInfoProvider alloc] init];
	geoProvider = [[AKTTTGeometryProvider alloc] init];
	imageProvider = [[AKTTTImageProvider alloc] init];
	stateMaintainer = [[AKTTTStateMaintainer alloc] init];
	
	aniProvider = [[AKBasicAnimationProvider alloc] init];
}

- (void)startGame {
	AKDrawing *drawing = [[AKDrawing alloc] initWithImageProvider:imageProvider
												animationProvider:aniProvider
												 geometryProvider:geoProvider
												basicInfoProvider:infoProvider
														 drawView:self.contentView];
	
	AKMediator *mediator = [[AKMediator alloc] initWithStateMaintainer:stateMaintainer
															   players:players 
														  basicDrawing:drawing];
	for (id <AKPlayer> aPlayer in players) {
		if ([(id)aPlayer isKindOfClass:[AKUIHumanPlayer class]]) {
			((AKUIHumanPlayer*)aPlayer).interactiveDrawing = drawing;
			((AKUIHumanPlayer*)aPlayer).stateMaintainer = stateMaintainer;
		}
	}
	
	[mediator start];
	
	// Show window
	[window makeKeyAndVisible];	
}

- (void)dealloc {
	[contentView release];
	[window release];
	[super dealloc];
}

@end

@implementation AKUIAppDelegate

- (id)init {
	self = [super init];
	if (self != nil) {
		canReceiveAlert = NO;
	}
	return self;
}


- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	if (canReceiveAlert) {
		canReceiveAlert = NO;
		if (buttonIndex == 0) {
			container.gameType = kAKUIAppDelegateTicTacToe;
			[container assembleTicTacToe];
		} else if (buttonIndex == 1) {
			container.gameType = kAKUIAppDelegateOthello;
			[container assembleOthello];
		} else
			NSAssert(NO, @"Which button you're pressed??");
		
		[container createWindowAndView];
		[container startGame];
	}
}

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	
	// Determine if should start a new game or resume a previous game
	container = nil;//[NSKeyedUnarchiver unarchiveObjectWithFile:kAKUIAppDelegateArchivedFileName];
	
	if (container != nil) {
		[container createWindowAndView];
		[container startGame];
	} else {
		container = [[AKUIContainer alloc] init];
		// Ask the player which game to play
		UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Choose a game" 
															message:@"Which game you wanna play?"
														   delegate:self
												  cancelButtonTitle:@"Tic Tac Toe" 
												  otherButtonTitles:@"Othello", nil];
		canReceiveAlert = YES;
		[alertView show];
	}
}

- (void)applicationWillTerminate:(UIApplication *)application {
	// Archiving data here
	[NSKeyedArchiver archiveRootObject:container toFile:kAKUIAppDelegateArchivedFileName];
}

@end
